TypeScript 93.3%
JavaScript 4.4%
CSS 2.3%
1/**2 * Author: Simon-Pierre Boucher3 * Contact: contact@spboucher.ai4 * Project: Hilmacorp.ai — Web Platform5 * File: app/[locale]/services/page.tsx6 * Description: Services page — the eight practice areas as anchored sections, plus engagement model7 */89import type { Metadata } from "next";10import Link from "next/link";11import Container from "@/components/Container";12import SectionHeading from "@/components/SectionHeading";13import { getMessages, isLocale, type Locale } from "@/lib/i18n";1415export async function generateMetadata({16 params,17}: {18 params: Promise<{ locale: string }>;19}): Promise<Metadata> {20 const { locale } = await params;21 if (!isLocale(locale)) return {};22 const { meta } = getMessages(locale);23 return { title: { absolute: meta.services.title }, description: meta.services.description };24}2526export default async function ServicesPage({27 params,28}: {29 params: Promise<{ locale: string }>;30}) {31 const { locale } = await params;32 const typedLocale = locale as Locale;33 const { services, nav } = getMessages(typedLocale);3435 return (36 <>37 <section className="relative overflow-hidden border-b border-line">38 <div className="grid-backdrop absolute inset-0" aria-hidden="true" />39 <Container className="relative py-20 sm:py-28">40 <SectionHeading as="h1" title={services.title} lead={services.lead} />41 <nav aria-label="Services index" className="mt-10 flex flex-wrap gap-2">42 {services.items.map((service) => (43 <a44 key={service.id}45 href={`#${service.id}`}46 className="rounded-full border border-line-strong bg-card px-4 py-1.5 text-sm text-ink-soft transition-colors hover:border-accent hover:text-accent"47 >48 {service.title}49 </a>50 ))}51 </nav>52 </Container>53 </section>5455 <section className="py-16 sm:py-20">56 <Container>57 <div className="grid gap-6 lg:grid-cols-2">58 {services.items.map((service, index) => (59 <article60 key={service.id}61 id={service.id}62 className="scroll-mt-24 rounded-3xl border border-line bg-card p-8 shadow-sm sm:p-10"63 >64 <p className="font-mono text-sm text-accent">65 {String(index + 1).padStart(2, "0")}66 </p>67 <h2 className="mt-3 font-display text-2xl font-semibold tracking-tight text-ink">68 {service.title}69 </h2>70 <p className="mt-4 leading-relaxed text-ink-soft">{service.description}</p>71 <ul className="mt-6 grid gap-2.5">72 {service.points.map((point) => (73 <li key={point} className="flex items-start gap-2.5 text-sm text-ink">74 <svg75 width="16"76 height="16"77 viewBox="0 0 16 16"78 fill="none"79 aria-hidden="true"80 className="mt-0.5 shrink-0"81 >82 <path83 d="M3 8.5l3.2 3L13 4.5"84 stroke="#0b6b4a"85 strokeWidth="1.8"86 strokeLinecap="round"87 strokeLinejoin="round"88 />89 </svg>90 {point}91 </li>92 ))}93 </ul>94 </article>95 ))}96 </div>97 </Container>98 </section>99100 {/* Engagement model */}101 <section className="border-t border-line bg-ink py-16 sm:py-20">102 <Container className="text-center">103 <h2 className="font-display text-2xl font-semibold tracking-tight text-paper sm:text-3xl">104 {services.engagementTitle}105 </h2>106 <p className="mx-auto mt-4 max-w-3xl leading-relaxed text-paper/70">107 {services.engagementBody}108 </p>109 <Link110 href={`/${typedLocale}/contact`}111 className="mt-8 inline-block rounded-full bg-paper px-8 py-3.5 text-sm font-medium text-ink transition-colors hover:bg-accent-soft"112 >113 {nav.cta}114 </Link>115 </Container>116 </section>117 </>118 );119}120